package kube

import prompt "github.com/c-bata/go-prompt"

var commands = []prompt.Suggest{
	{Text: "get", Description: "显示一个或多个资源"},
	{Text: "describe", Description: "显示特定资源或资源组的详细信息"},
	{Text: "create", Description: "按文件名或stdin创建资源"},
	{Text: "replace", Description: "用文件名或stdin替换资源。"},
	{Text: "patch", Description: "使用策略合并修补程序更新资源的字段。"},
	{Text: "delete", Description: "按文件名、stdin、资源和名称，或按资源和标签选择器删除资源。"},
	{Text: "edit", Description: "编辑服务器上的资源"},
	{Text: "apply", Description: "通过文件名或stdin对资源应用配置"},
	{Text: "namespace", Description: "被取代：设置或查看当前的Kubernetes命名空间"},
	{Text: "logs", Description: "打印pod中容器的日志。"},
	{Text: "rolling-update", Description: "对给定的控制器执行滚动更新。"},
	{Text: "scale", Description: "设置Deployment, ReplicaSet, Replication Controller, Job 实例数量"},
	{Text: "cordon", Description: "停止调度"},
	{Text: "drain", Description: "驱逐节点"},
	{Text: "uncordon", Description: "恢复调度"},
	{Text: "attach", Description: "连接到一个正在运行的容器。"},
	{Text: "exec", Description: "在容器内部执行命令。"},
	{Text: "port-forward", Description: "通过端口转发映射本地端口到指定的应用端口"},
	{Text: "proxy", Description: "运行kubernetesapi服务器的代理"},
	{Text: "run", Description: "创建并运行一个或多个容器镜像。"},
	{Text: "expose", Description: "将资源暴露为新的Kubernetes Service。"},
	{Text: "autoscale", Description: "使用 autoscaler 自动设置在kubernetes集群中运行的pod数量（水平自动伸缩）。"},
	{Text: "rollout", Description: "对资源进行管理,可用资源包括：[deployments, daemonsets]"},
	{Text: "label", Description: "更新（增加、修改或删除）资源上的 label（标签）。"},
	{Text: "annotate", Description: "更新一个或多个资源的Annotations信息。"},
	{Text: "config", Description: "使用config的子命令修改kubeconfig配置文件，如“kubectl config set current-context my-context”。"},
	{Text: "cluster-info", Description: "显示master节点的地址和包含kubernetes.io/cluster-service=true的service（系统service）。"},
	{Text: "api-versions", Description: "以“组/版本”的格式输出服务端支持的API版本。"},
	{Text: "version", Description: "输出服务端和客户端的版本信息。"},
	{Text: "explain", Description: "获取各种资源的文档。例如pod，node，services等"},
	{Text: "convert", Description: "转换配置文件为不同的API版本，支持YAML和JSON格式。"},
	{Text: "top", Description: "查看node、pod 的实时资源使用情况"},

	// Custom command.
	{Text: "exit", Description: "退出此程序"},
}

var resourceTypes = []prompt.Suggest{
	{Text: "clusters"}, // valid only for federation apiservers
	{Text: "componentstatuses"},
	{Text: "configmaps"},
	{Text: "daemonsets"},
	{Text: "deployments"},
	{Text: "endpoints"},
	{Text: "events"},
	{Text: "horizontalpodautoscalers"},
	{Text: "ingresses"},
	{Text: "jobs"},
	{Text: "cronjobs"},
	{Text: "limitranges"},
	{Text: "namespaces"},
	{Text: "networkpolicies"},
	{Text: "nodes"},
	{Text: "persistentvolumeclaims"},
	{Text: "persistentvolumes"},
	{Text: "pod"},
	{Text: "podsecuritypolicies"},
	{Text: "podtemplates"},
	{Text: "replicasets"},
	{Text: "replicationcontrollers"},
	{Text: "resourcequotas"},
	{Text: "secrets"},
	{Text: "serviceaccounts"},
	{Text: "services"},
	{Text: "statefulsets"},
	{Text: "storageclasses"},
	{Text: "thirdpartyresources"},

	// aliases
	{Text: "cs"},
	{Text: "cm"},
	{Text: "ds"},
	{Text: "deploy"},
	{Text: "ep"},
	{Text: "hpa"},
	{Text: "ing"},
	{Text: "limits"},
	{Text: "ns"},
	{Text: "no"},
	{Text: "pvc"},
	{Text: "pv"},
	{Text: "po"},
	{Text: "psp"},
	{Text: "rs"},
	{Text: "rc"},
	{Text: "quota"},
	{Text: "sa"},
	{Text: "svc"},
}

func (c *Completer) argumentsCompleter(namespace string, args []string) []prompt.Suggest {
	if len(args) <= 1 {
		return prompt.FilterHasPrefix(commands, args[0], true)
	}

	first := args[0]
	switch first {
	case "get":
		second := args[1]
		if len(args) == 2 {
			subcommands := []prompt.Suggest{
				{Text: "componentstatuses"},
				{Text: "configmaps"},
				{Text: "daemonsets"},
				{Text: "deployments"},
				{Text: "endpoints"},
				{Text: "events"},
				{Text: "horizontalpodautoscalers"},
				{Text: "ingresses"},
				{Text: "jobs"},
				{Text: "cronjobs"},
				{Text: "limitranges"},
				{Text: "namespaces"},
				{Text: "networkpolicies"},
				{Text: "nodes"},
				{Text: "persistentvolumeclaims"},
				{Text: "persistentvolumes"},
				{Text: "pod"},
				{Text: "podsecuritypolicies"},
				{Text: "podtemplates"},
				{Text: "replicasets"},
				{Text: "replicationcontrollers"},
				{Text: "resourcequotas"},
				{Text: "secrets"},
				{Text: "serviceaccounts"},
				{Text: "services"},
				{Text: "statefulsets"},
				{Text: "storageclasses"},
				{Text: "thirdpartyresources"},
				// aliases
				{Text: "cs"},
				{Text: "cm"},
				{Text: "ds"},
				{Text: "deploy"},
				{Text: "ep"},
				{Text: "hpa"},
				{Text: "ing"},
				{Text: "limits"},
				{Text: "ns"},
				{Text: "no"},
				{Text: "pvc"},
				{Text: "pv"},
				{Text: "po"},
				{Text: "psp"},
				{Text: "rs"},
				{Text: "rc"},
				{Text: "quota"},
				{Text: "sa"},
				{Text: "svc"},
			}
			return prompt.FilterHasPrefix(subcommands, second, true)
		}

		third := args[2]
		if len(args) == 3 {
			switch second {
			case "componentstatuses", "cs":
				return prompt.FilterContains(getComponentStatusCompletions(c.client), third, true)
			case "configmaps", "cm":
				return prompt.FilterContains(getConfigMapSuggestions(c.client, namespace), third, true)
			case "daemonsets", "ds":
				return prompt.FilterContains(getDaemonSetSuggestions(c.client, namespace), third, true)
			case "deploy", "deployments":
				return prompt.FilterContains(getDeploymentSuggestions(c.client, namespace), third, true)
			case "endpoints", "ep":
				return prompt.FilterContains(getEndpointsSuggestions(c.client, namespace), third, true)
			case "ingresses", "ing":
				return prompt.FilterContains(getIngressSuggestions(c.client, namespace), third, true)
			case "limitranges", "limits":
				return prompt.FilterContains(getLimitRangeSuggestions(c.client, namespace), third, true)
			case "namespaces", "ns":
				return prompt.FilterContains(getNameSpaceSuggestions(c.namespaceList), third, true)
			case "no", "nodes":
				return prompt.FilterContains(getNodeSuggestions(c.client), third, true)
			case "po", "pod", "pods":
				return prompt.FilterContains(getPodSuggestions(c.client, namespace), third, true)
			case "persistentvolumeclaims", "pvc":
				return prompt.FilterContains(getPersistentVolumeClaimSuggestions(c.client, namespace), third, true)
			case "persistentvolumes", "pv":
				return prompt.FilterContains(getPersistentVolumeSuggestions(c.client), third, true)
			case "podsecuritypolicies", "psp":
				return prompt.FilterContains(getPodSecurityPolicySuggestions(c.client), third, true)
			case "podtemplates":
				return prompt.FilterContains(getPodTemplateSuggestions(c.client, namespace), third, true)
			case "replicasets", "rs":
				return prompt.FilterContains(getReplicaSetSuggestions(c.client, namespace), third, true)
			case "replicationcontrollers", "rc":
				return prompt.FilterContains(getReplicationControllerSuggestions(c.client, namespace), third, true)
			case "resourcequotas", "quota":
				return prompt.FilterContains(getResourceQuotasSuggestions(c.client, namespace), third, true)
			case "secrets":
				return prompt.FilterContains(getSecretSuggestions(c.client, namespace), third, true)
			case "sa", "serviceaccounts":
				return prompt.FilterContains(getServiceAccountSuggestions(c.client, namespace), third, true)
			case "svc", "services":
				return prompt.FilterContains(getServiceSuggestions(c.client, namespace), third, true)
			case "job", "jobs":
				return prompt.FilterContains(getJobSuggestions(c.client, namespace), third, true)
			}
		}
	case "describe":
		second := args[1]
		if len(args) == 2 {
			return prompt.FilterHasPrefix(resourceTypes, second, true)
		}

		third := args[2]
		if len(args) == 3 {
			switch second {
			case "componentstatuses", "cs":
				return prompt.FilterContains(getComponentStatusCompletions(c.client), third, true)
			case "configmaps", "cm":
				return prompt.FilterContains(getConfigMapSuggestions(c.client, namespace), third, true)
			case "daemonsets", "ds":
				return prompt.FilterContains(getDaemonSetSuggestions(c.client, namespace), third, true)
			case "deploy", "deployments":
				return prompt.FilterContains(getDeploymentSuggestions(c.client, namespace), third, true)
			case "endpoints", "ep":
				return prompt.FilterContains(getEndpointsSuggestions(c.client, namespace), third, true)
			case "ingresses", "ing":
				return prompt.FilterContains(getIngressSuggestions(c.client, namespace), third, true)
			case "limitranges", "limits":
				return prompt.FilterContains(getLimitRangeSuggestions(c.client, namespace), third, true)
			case "namespaces", "ns":
				return prompt.FilterContains(getNameSpaceSuggestions(c.namespaceList), third, true)
			case "no", "nodes":
				return prompt.FilterContains(getNodeSuggestions(c.client), third, true)
			case "po", "pod", "pods":
				return prompt.FilterContains(getPodSuggestions(c.client, namespace), third, true)
			case "persistentvolumeclaims", "pvc":
				return prompt.FilterContains(getPersistentVolumeClaimSuggestions(c.client, namespace), third, true)
			case "persistentvolumes", "pv":
				return prompt.FilterContains(getPersistentVolumeSuggestions(c.client), third, true)
			case "podsecuritypolicies", "psp":
				return prompt.FilterContains(getPodSecurityPolicySuggestions(c.client), third, true)
			case "podtemplates":
				return prompt.FilterContains(getPodTemplateSuggestions(c.client, namespace), third, true)
			case "replicasets", "rs":
				return prompt.FilterContains(getReplicaSetSuggestions(c.client, namespace), third, true)
			case "replicationcontrollers", "rc":
				return prompt.FilterContains(getReplicationControllerSuggestions(c.client, namespace), third, true)
			case "resourcequotas", "quota":
				return prompt.FilterContains(getResourceQuotasSuggestions(c.client, namespace), third, true)
			case "secrets":
				return prompt.FilterContains(getSecretSuggestions(c.client, namespace), third, true)
			case "sa", "serviceaccounts":
				return prompt.FilterContains(getServiceAccountSuggestions(c.client, namespace), third, true)
			case "svc", "services":
				return prompt.FilterContains(getServiceSuggestions(c.client, namespace), third, true)
			case "job", "jobs":
				return prompt.FilterContains(getJobSuggestions(c.client, namespace), third, true)
			}
		}
	case "create":
		subcommands := []prompt.Suggest{
			{Text: "configmap", Description: "ConfigMap用于保存配置数据的键值对，可以用来保存单个属性，也可以用来保存配置文件。ConfigMap跟secret很类似，但它可以更方便地处理不包含敏感信息的字符串。"},
			{Text: "deployment", Description: "创建具有指定名称的deployment 。"},
			{Text: "namespace", Description: "创建namespace"},
			{Text: "quota", Description: "创建具有指定名称、hard限制和可选scopes的resourcequota"},
			{Text: "secret", Description: "使用指定的子命令创建 secret。"},
			{Text: "service", Description: "使用指定的子命令创建 Service服务。"},
			{Text: "serviceaccount", Description: "创建指定名称的service account。"},
		}
		if len(args) == 2 {
			return prompt.FilterHasPrefix(subcommands, args[1], true)
		}
	case "delete":
		second := args[1]
		if len(args) == 2 {
			return prompt.FilterHasPrefix(resourceTypes, second, true)
		}

		third := args[2]
		if len(args) == 3 {
			switch second {
			case "componentstatuses", "cs":
				return prompt.FilterContains(getComponentStatusCompletions(c.client), third, true)
			case "configmaps", "cm":
				return prompt.FilterContains(getConfigMapSuggestions(c.client, namespace), third, true)
			case "daemonsets", "ds":
				return prompt.FilterContains(getDaemonSetSuggestions(c.client, namespace), third, true)
			case "deploy", "deployments":
				return prompt.FilterContains(getDeploymentSuggestions(c.client, namespace), third, true)
			case "endpoints", "ep":
				return prompt.FilterContains(getEndpointsSuggestions(c.client, namespace), third, true)
			case "ingresses", "ing":
				return prompt.FilterContains(getIngressSuggestions(c.client, namespace), third, true)
			case "limitranges", "limits":
				return prompt.FilterContains(getLimitRangeSuggestions(c.client, namespace), third, true)
			case "namespaces", "ns":
				return prompt.FilterContains(getNameSpaceSuggestions(c.namespaceList), third, true)
			case "no", "nodes":
				return prompt.FilterContains(getNodeSuggestions(c.client), third, true)
			case "po", "pod", "pods":
				return prompt.FilterContains(getPodSuggestions(c.client, namespace), third, true)
			case "persistentvolumeclaims", "pvc":
				return prompt.FilterContains(getPersistentVolumeClaimSuggestions(c.client, namespace), third, true)
			case "persistentvolumes", "pv":
				return prompt.FilterContains(getPersistentVolumeSuggestions(c.client), third, true)
			case "podsecuritypolicies", "psp":
				return prompt.FilterContains(getPodSecurityPolicySuggestions(c.client), third, true)
			case "podtemplates":
				return prompt.FilterContains(getPodTemplateSuggestions(c.client, namespace), third, true)
			case "replicasets", "rs":
				return prompt.FilterContains(getReplicaSetSuggestions(c.client, namespace), third, true)
			case "replicationcontrollers", "rc":
				return prompt.FilterContains(getReplicationControllerSuggestions(c.client, namespace), third, true)
			case "resourcequotas", "quota":
				return prompt.FilterContains(getResourceQuotasSuggestions(c.client, namespace), third, true)
			case "secrets":
				return prompt.FilterContains(getSecretSuggestions(c.client, namespace), third, true)
			case "sa", "serviceaccounts":
				return prompt.FilterContains(getServiceAccountSuggestions(c.client, namespace), third, true)
			case "svc", "services":
				return prompt.FilterContains(getServiceSuggestions(c.client, namespace), third, true)
			case "job", "jobs":
				return prompt.FilterContains(getJobSuggestions(c.client, namespace), third, true)
			}
		}
	case "edit":
		if len(args) == 2 {
			return prompt.FilterHasPrefix(resourceTypes, args[1], true)
		}

		if len(args) == 3 {
			third := args[2]
			switch args[1] {
			case "componentstatuses", "cs":
				return prompt.FilterContains(getComponentStatusCompletions(c.client), third, true)
			case "configmaps", "cm":
				return prompt.FilterContains(getConfigMapSuggestions(c.client, namespace), third, true)
			case "daemonsets", "ds":
				return prompt.FilterContains(getDaemonSetSuggestions(c.client, namespace), third, true)
			case "deploy", "deployments":
				return prompt.FilterContains(getDeploymentSuggestions(c.client, namespace), third, true)
			case "endpoints", "ep":
				return prompt.FilterContains(getEndpointsSuggestions(c.client, namespace), third, true)
			case "ingresses", "ing":
				return prompt.FilterContains(getIngressSuggestions(c.client, namespace), third, true)
			case "limitranges", "limits":
				return prompt.FilterContains(getLimitRangeSuggestions(c.client, namespace), third, true)
			case "namespaces", "ns":
				return prompt.FilterContains(getNameSpaceSuggestions(c.namespaceList), third, true)
			case "no", "nodes":
				return prompt.FilterContains(getNodeSuggestions(c.client), third, true)
			case "po", "pod", "pods":
				return prompt.FilterContains(getPodSuggestions(c.client, namespace), third, true)
			case "persistentvolumeclaims", "pvc":
				return prompt.FilterContains(getPersistentVolumeClaimSuggestions(c.client, namespace), third, true)
			case "persistentvolumes", "pv":
				return prompt.FilterContains(getPersistentVolumeSuggestions(c.client), third, true)
			case "podsecuritypolicies", "psp":
				return prompt.FilterContains(getPodSecurityPolicySuggestions(c.client), third, true)
			case "podtemplates":
				return prompt.FilterContains(getPodTemplateSuggestions(c.client, namespace), third, true)
			case "replicasets", "rs":
				return prompt.FilterContains(getReplicaSetSuggestions(c.client, namespace), third, true)
			case "replicationcontrollers", "rc":
				return prompt.FilterContains(getReplicationControllerSuggestions(c.client, namespace), third, true)
			case "resourcequotas", "quota":
				return prompt.FilterContains(getResourceQuotasSuggestions(c.client, namespace), third, true)
			case "secrets":
				return prompt.FilterContains(getSecretSuggestions(c.client, namespace), third, true)
			case "sa", "serviceaccounts":
				return prompt.FilterContains(getServiceAccountSuggestions(c.client, namespace), third, true)
			case "svc", "services":
				return prompt.FilterContains(getServiceSuggestions(c.client, namespace), third, true)
			case "job", "jobs":
				return prompt.FilterContains(getJobSuggestions(c.client, namespace), third, true)
			}
		}

	case "namespace":
		if len(args) == 2 {
			return prompt.FilterContains(getNameSpaceSuggestions(c.namespaceList), args[1], true)
		}
	case "logs":
		if len(args) == 2 {
			return prompt.FilterContains(getPodSuggestions(c.client, namespace), args[1], true)
		}
	case "rolling-update", "rollingupdate":
		if len(args) == 2 {
			return prompt.FilterContains(getReplicationControllerSuggestions(c.client, namespace), args[1], true)
		} else if len(args) == 3 {
			return prompt.FilterContains(getReplicationControllerSuggestions(c.client, namespace), args[2], true)
		}
	case "scale", "resize":
		if len(args) == 2 {
			// Deployment, ReplicaSet, Replication Controller, or Job.
			r := getDeploymentSuggestions(c.client, namespace)
			r = append(r, getReplicaSetSuggestions(c.client, namespace)...)
			r = append(r, getReplicationControllerSuggestions(c.client, namespace)...)
			return prompt.FilterContains(r, args[1], true)
		}
	case "cordon":
		fallthrough
	case "drain":
		fallthrough
	case "uncordon":
		if len(args) == 2 {
			return prompt.FilterHasPrefix(getNodeSuggestions(c.client), args[1], true)
		}
	case "attach":
		if len(args) == 2 {
			return prompt.FilterContains(getPodSuggestions(c.client, namespace), args[1], true)
		}
	case "exec":
		if len(args) == 2 {
			return prompt.FilterContains(getPodSuggestions(c.client, namespace), args[1], true)
		}
	case "port-forward":
		if len(args) == 2 {
			return prompt.FilterContains(getPodSuggestions(c.client, namespace), args[1], true)
		}
		if len(args) == 3 {
			return prompt.FilterHasPrefix(getPortsFromPodName(namespace, args[1]), args[2], true)
		}
	case "rollout":
		subCommands := []prompt.Suggest{
			{Text: "history", Description: "查看历史版本"},
			{Text: "pause", Description: "暂停资源"},
			{Text: "resume", Description: "恢复暂停资源"},
			{Text: "undo", Description: "回滚版本"},
		}
		if len(args) == 2 {
			return prompt.FilterHasPrefix(subCommands, args[1], true)
		}
	case "annotate":
	case "config":
		subCommands := []prompt.Suggest{
			{Text: "current-context", Description: "显示当前上下文"},
			{Text: "delete-cluster", Description: "从kubeconfig中删除指定的群集"},
			{Text: "delete-context", Description: "从kubeconfig中删除指定的上下文"},
			{Text: "get-clusters", Description: "显示在kubeconfig中定义的集群"},
			{Text: "get-contexts", Description: "描述一个或多个上下文"},
			{Text: "set", Description: "设置kubeconfig文件中的单个值"},
			{Text: "set-cluster", Description: "在kubeconfig中设置集群条目"},
			{Text: "set-context", Description: "在kubeconfig中设置上下文项"},
			{Text: "set-credentials", Description: "在kubeconfig中设置用户条目"},
			{Text: "unset", Description: "取消设置kubeconfig文件中的单个值"},
			{Text: "use-context", Description: "设置kubeconfig文件中的当前上下文"},
			{Text: "view", Description: "显示合并的kubeconfig设置或指定的kubeconfig文件"},
		}
		if len(args) == 2 {
			return prompt.FilterHasPrefix(subCommands, args[1], true)
		}
		if len(args) == 3 {
			third := args[2]
			switch args[1] {
			case "use-context":
				return prompt.FilterContains(getContextSuggestions(), third, true)
			}
		}
	case "cluster-info":
		subCommands := []prompt.Suggest{
			{Text: "dump", Description: "为调试和诊断转储大量相关信息"},
		}
		if len(args) == 2 {
			return prompt.FilterHasPrefix(subCommands, args[1], true)
		}
	case "explain":
		return prompt.FilterHasPrefix(resourceTypes, args[1], true)
	case "top":
		second := args[1]
		if len(args) == 2 {
			subcommands := []prompt.Suggest{
				{Text: "nodes"},
				{Text: "pod"},
				// aliases
				{Text: "no"},
				{Text: "po"},
			}
			return prompt.FilterHasPrefix(subcommands, second, true)
		}

		third := args[2]
		if len(args) == 3 {
			switch second {
			case "no", "node", "nodes":
				return prompt.FilterContains(getNodeSuggestions(c.client), third, true)
			case "po", "pod", "pods":
				return prompt.FilterContains(getPodSuggestions(c.client, namespace), third, true)
			}
		}
	default:
		return []prompt.Suggest{}
	}
	return []prompt.Suggest{}
}
